---OOSE SoSe 2011 Aufgabe 3
--@author Mickey Reiss <mickeyreiss@gmail.com> (HU:417884)

require('gameClass')
require'kalahaBoard'

--Kalaha Configuration
local config = {
  seedsPerPit = 3,
  numPits = 6,
}

Class{'Kalaha', Game, board = KalahaBoard}

--  -------------
-- | 1 2 3 4 5 6 | --Player A
-- | 1 2 3 4 5 6 | --Player B
--  -------------

---Initialize a new game of Kalaha
function Kalaha:init()
  super:init()

  self.player1.name = "A"
  self.player2.name = "B"

  self.board = KalahaBoard:create()
  self.board:init(config.numPits, config.seedsPerPit)
end

---Validates requested moves based on the rules of Kalaha:
--1. Pit must be between 1 and 6,
--2. Pit must contain non-zero number of seeds
--@returns true if valid, false otherwise
function Kalaha:validateMove(input)
  if not (1 <= input and input <= config.numPits) then
    return false
  end

  if self.board:peek(self:currentPlayerNumber(), input) <= 0 then
    return false
  end

  return true
end

---Execute a standard Kalaha move
--1. Sow the seeds
--2. Check for the last seed landing in the current player's store
--3. Check for the last seed landing in a previously empty pit with bounty across the board
--@returns the player who should play next
function Kalaha:doMove(input)
  --Sow the seeds
  local result
  local where = self.board:pickUp(self:currentPlayerNumber(), input)
  if self.board.hand == 0 then
    print("Field "..input.." is empty. Please choose another one.")
  end
  while self.board.hand > 0 do
    result = self.board:drop(where)
    where = result.nextPit
    --Make sure to skip your opponent's store
    if where == self.board:getStoreIndex(self:currentPlayerNumber()%2+1) then
      self.logger:fine("We skip opponent's store")
      where = self.board:nextPit(result.nextPit)
    end
  end

  --The last seed landed in the store
  if result.wasStore then
    return self.currentPlayer
  end

  --The last seed landed in an empty store on the current player's side
  if result.newTotal == 1 
  and result.wasStore == false 
  and result.player == self:currentPlayerNumber() 
  and self.board:peek(result.player%2+1, result.pit) > 0 --Other side, not empty
  then
    --pick up and capture this last piece
    self.board:pickUp(result.player, result.pit)
    self.board:drop(self.board:getStoreIndex(result.player), -1)

    --pick up and capture the bounty on the other side
    self.board:pickUp(result.player%2+1, result.pit)
    self.board:drop(self.board:getStoreIndex(result.player), -1)
  end

  --Nothing special happened, so it should be the other player's turn next.
  if self.currentPlayer == self.player1 then
    return self.player2
  else
    return self.player1
  end
end

--Returns true if a side (0 or 1) is completely empty
function Kalaha:side_empty(side)
  assert(side == 0 or side == 1)
  side = side+1
  self.logger:finer("Checking if side "..side.." is empty")
  for i=1,6 do
    if 0 < self.board:peek(side, i) then
      return false
    end
  end
  self.logger:info("And it is!")
  return true
end

--Private function to clean up the Kalaha board
--seeds in pits -> appropriate stores
function Kalaha:cleanup()
  --Clean up each player's tiles independently
  for player = 1, 2 do --for each player
    for pit = 1, config.numPits do
      self.board:pickUp(player, pit)
      self.board:drop(self.board:getStoreIndex(player), -1)
    end
  end
end

--Get scores: [Player 1, Player 2]
function Kalaha:getScores()
  return self.board:getScores()
end

--Returns winner:Player, beendet:boolean
function Kalaha:checkVictory()
  self.logger:info("Checking victory")
  self.logger:fine(self.board:toString())

  if self:side_empty(0) or self:side_empty(1) then
    --Clean up
    self:cleanup()
    local score1, score2 = self:getScores()
    assert(type(score1)=="number" and type(score2)=="number")
    if score1 == score2 then --TIE
      return nil, true
    elseif score1 > score2 then --Player 1 won
      return self.player1, true
    elseif score1 < score2 then --Player 2 won
      return self.player2, true
    else
      print("1:"..score1)
      print("2:"..score2)
      ierror("Someone had to win")
    end
  else
    return nil, false
  end
end

---Return 1 or 2 corresponding to the number of the current player
function Kalaha:currentPlayerNumber()
  if self.currentPlayer == self.player1 then
    return 1
  else
    return 2
  end
end

function Kalaha:getPossibleTurns()
  local turns = {}
  for i=1,config.numPits do
    if self.board:peek(self:currentPlayerNumber(), i) > 0 then
      table.insert(turns, i)
    end
  end
  return turns
end

function Kalaha:printPossibleTurns()
	local output = 'Possible moves: '
	for i, v in ipairs(self:getPossibleTurns()) do
		output = output..v..' '
	end
	print(output)
end

function Kalaha:print()
  print(self.board:toString())
end

function Kalaha:checkMoveInput(nr)
	if not isNumber(nr) 
    or 1 > nr 
    or nr > config.numPits
    then
		print('expected 1-'..config.numPits..', but your input was: ',nr)
    return false
  else 
    return true
  end
end
